package com.songlanyun.modules.wechat.controller;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import cn.binarywang.wx.miniapp.bean.WxMaUserInfo;
import com.songlanyun.common.utils.R;
import com.songlanyun.modules.wechat.config.WxMaConfiguration;
import com.songlanyun.modules.wechat.utils.JsonUtils;
import me.chanjar.weixin.common.error.WxErrorException;
import org.apache.commons.lang3.StringUtils;
import org.bouncycastle.util.encoders.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.*;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Map;

/**
 * 微信小程序用户接口
 *
 * @author <a href="https://github.com/binarywang">Binary Wang</a>
 */
@RestController
@RequestMapping("/api/wx/user")
public class WxMaUserController {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * 登陆接口 获取openid,sessionkey 来获取手机号敏感信息
     */
    @RequestMapping(value = "/getOpenId", method = {RequestMethod.POST})
    public R getOpenId(@RequestBody Map<String, Object> param) {
        String appid = param.get("appid").toString();
        String code = param.get("code").toString();

        if (StringUtils.isBlank(code)) {
            return R.error("empty jscode");
        }
        final WxMaService wxService = WxMaConfiguration.getMaService(appid);

        try {
            WxMaJscode2SessionResult session = wxService.getUserService().getSessionInfo(code);
            this.logger.info(session.getSessionKey());
            this.logger.info(session.getOpenid());
            //TODO 可以增加自己的逻辑，关联业务相关数据
            return R.ok("获取用户openid成功").put("data", session);
        } catch (WxErrorException e) {
            this.logger.error(e.getMessage(), e);
            return R.error(e.toString());
        }
    }

    /**
     * <pre>
     * 获取用户信息接口
     * </pre>
     */
    @RequestMapping(value = "/info", method = {RequestMethod.POST})
    public R getWxUserInfo(@RequestBody Map<String, Object> param) {
        String appid = param.containsKey("appid") ? param.get("appid").toString() : "";
        String sessionKey = param.containsKey("sessionKey") ? param.get("sessionKey").toString() : "";
        String signature = param.containsKey("signature") ? param.get("signature").toString() : "";
        String rawData = param.containsKey("rawData") ? param.get("rawData").toString() : "";
        String encryptedData = param.containsKey("encryptedData") ? param.get("encryptedData").toString() : "";
        String iv = param.containsKey("iv") ? param.get("iv").toString() : "";
        final WxMaService wxService = WxMaConfiguration.getMaService(appid);
        // 用户信息校验
        if (!wxService.getUserService().checkUserInfo(sessionKey, rawData, signature)) {
            return R.error("用户信息检测失败");
        }
        // 解密用户信息
        WxMaUserInfo userInfo = wxService.getUserService().getUserInfo(sessionKey, encryptedData, iv);
        // 解密
        //  WxMaPhoneNumberInfo phoneNoInfo = wxService.getUserService().getPhoneNoInfo(sessionKey, encryptedData, iv);

        return R.ok().put("data", userInfo);
    }

    /**
     * 解密用户手机号
     */
    @RequestMapping(value = "/getTel", method = {RequestMethod.POST})
    public R decryptPhone(@RequestBody Map<String, Object> param) throws Exception {
        String keyStr = param.get("sessionKey").toString();  // sessionkey
        String encDataStr = param.get("encryptedData").toString();
        String ivStr = param.get("iv").toString();

        byte[] encData = Base64.decode(encDataStr);
        byte[] iv = Base64.decode(ivStr);
        byte[] key = Base64.decode(keyStr);

        AlgorithmParameterSpec ivSpec = new IvParameterSpec(iv);
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
        cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
        return R.ok().put("data", new String(cipher.doFinal(encData), "UTF-8"));
    }

    /**
     * <pre>
     * 获取用户绑定手机号信息
     * </pre>
     */
    @GetMapping("/phone")
    public String phone(@PathVariable String appid, String sessionKey, String signature,
                        String rawData, String encryptedData, String iv) {
        final WxMaService wxService = WxMaConfiguration.getMaService(appid);

        // 用户信息校验
        if (!wxService.getUserService().checkUserInfo(sessionKey, rawData, signature)) {
            return "user check failed";
        }

        // 解密
        WxMaPhoneNumberInfo phoneNoInfo = wxService.getUserService().getPhoneNoInfo(sessionKey, encryptedData, iv);

        return JsonUtils.toJson(phoneNoInfo);
    }


}
